这段时间在做 Android 多渠道可自定义打包的工作,测试过程中发现经过反编译后再重新压缩签名打包后的 apk 文件总是要比原文件更小一些。
而且在部分游戏 apk 中反编译压缩重新出包甚至会导致游戏动画加载黑屏的情况。
问题定位
apk 文件也是一个压缩文件,可以使用 zipinfo
命令查看压缩信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| >> zipinfo test.apk
Zip file size: 17426 bytes, number of entries: 12 -rw---- 0.0 fat 2132 b- defN 80-000-00 00:00 AndroidManifest.xml -rw---- 2.4 fat 765 b- defN 80-000-00 00:00 META-INF/CERT.RSA -rw---- 2.4 fat 836 b- defN 80-000-00 00:00 META-INF/CERT.SF -rw---- 2.4 fat 793 b- defN 80-000-00 00:00 META-INF/MANIFEST.MF -rw---- 2.4 fat 10656 b- defN 80-000-00 00:00 classes.dex -rw---- 2.4 fat 642 b- stor 80-000-00 00:00 res/drawable-hdpi-v4/ic_launcher.png -rw---- 2.4 fat 566 b- stor 80-000-00 00:00 res/drawable-mdpi-v4/ic_launcher.png -rw---- 2.4 fat 688 b- stor 80-000-00 00:00 res/drawable-xhdpi-v4/ic_launcher.png -rw---- 2.4 fat 824 b- stor 80-000-00 00:00 res/drawable-xxhdpi-v4/ic_launcher.png -rw---- 0.0 fat 608 b- defN 80-000-00 00:00 res/layout/view.xml -rw---- 0.0 fat 236 b- defN 80-000-00 00:00 res/xml/methods.xml -rw---- 0.0 fat 1904 b- stor 80-000-00 00:00 resources.arsc 12 files, 20650 bytes uncompressed, 10917 bytes compressed: 47.1%
|
stor
表示压缩类型是 store
,即不压缩,defN
表示默认压缩, 参考 oracle zipinfo
可以发现,Android apk 对于很多媒体资源类型的文件是不压缩的。而如果我在反编译之后直接使用 zip
命令压缩打包,那默认会对所有文件做压缩处理,最终得到的 apk 体积就会更小一些。
这样做自然是有风险的,经过测试,如果对一个游戏包做这样的处理,有可能会导致游戏打开直接黑屏,实际上它应该是有一段开屏动画的。Android 游戏的开屏动画往往是一个视频,经过压缩后可能就无法正常播放。
非压缩处理
参考官方文档的说明, 特别是对于游戏类的 App 而言,对这类文件需要按非压缩类型处理。处理方式:
zip -rn .mp4:.flv:.mp3:.gif:.lua:assets/bundle.json
-n
表示不压缩此后缀的文件,多个规则用:
隔开
-x
表示忽略该文件,不加入压缩包
实际上,使用 apktool
反编译后的文件夹里有一个配置文件apktool.yml
,里面有一项 doNotCompress
:
1 2 3 4 5 6 7
| doNotCompress: - resources.arsc - assets/.appkey - png - jpg - ogg - mp3
|
表示原 apk 中以非压缩形式存储的文件类型/文件。因此如果我们需要在反编译之后做自定义操作,并使用 zip
打包的话,可以结合 apktool.yml
这个文件对原 apk 包内的非压缩文件做特殊处理。